{
  // 之前实现的 给索引加上 readonly修饰

  type ToReadonly<T> = {
    readonly [K in keyof T]: T[K];
  };

  // 如果索引层数不确定？应使用递归

  type DeepReadonly<T extends Record<string, any>> = {
    readonly [K in keyof T]: T[K] extends object
      ? T[K] extends Function
        ? T[K]
        : DeepReadonly<T[K]>
      : T[K];
  };

  interface Obj {
    a: number;
    b: string;
    c: {
      d: number;
      e: {
        f: boolean;
      };
      g: () => void;
    };
  }

  type res = DeepReadonly<Obj>;
  type res2 = DeepReadonly<Obj>['c'];
  type res3 = DeepReadonly<Obj>['c']['e'];

  /*
    类型参数 Obj 是待处理的索引类型，约束为 Record<string, any>，也就是索引为 string，值为任意类型的索引类型。

    索引映射自之前的索引，也就是 Key in keyof Obj，只不过加上了 readonly 的修饰。

    值要做下判断，如果是 object 类型并且还是 Function，那么就直接取之前的值 Obj[Key]。

    如果是 object 类型但不是 Function，那就是说也是一个索引类型，就递归处理 DeepReadonly<Obj[Key]>

    否则，值不是 object 就直接返回之前的值 Obj[Key]。

    这样就完成了任意层数的索引类型的添加 readonly 修饰：
  */
}
